package com.africanmoviesmobile.ui;

import java.io.IOException;
import java.util.Hashtable;
import java.util.Vector;

import org.pixmob.httpclient.HttpClientException;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import com.africanmoviesmobile.R;
import com.africanmoviesmobile.util.bitmap.ImageCache.ImageCacheParams;
import com.africanmoviesmobile.util.bitmap.ImageFetcher;
import com.africanmoviesmobile.webservice.AmmWebService;
import com.africanmoviesmobile.webservice.BasicAsyncCallback;
import com.africanmoviesmobile.webservice.WebServiceException;
import com.africanmoviesmobile.webservice.inf.Movie;
import com.africanmoviesmobile.webservice.inf.WebserviceObject;

public class MovieListActivity  extends BaseActivity implements OnItemClickListener, OnScrollListener {
	
	private LayoutInflater mLayoutInflater;
	private ListView mMovieListView;
	private LinearLayout mLoadingProgress;
	
	private ImageFetcher mThumbnailImageFetcher;
	
	AmmWebService mAmmWebService;
	
	private MovieListAdapter mMovieListAdapter;
	
	private boolean mLastItemVisible = false;
    private boolean mLoadingInProgress = false;
	private int mResultPage;
	private int mPageCount;
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.movie_list_activity);
		   
		int thumbnailWidth = getResources().getDimensionPixelSize(R.dimen.thumbnail_width);
		int thumbnailHeight = getResources().getDimensionPixelSize(R.dimen.thumbnail_height);
		mThumbnailImageFetcher = new ImageFetcher(this, thumbnailWidth, thumbnailHeight);
		mThumbnailImageFetcher.setLoadingImage(R.drawable.empty_photo);
		mThumbnailImageFetcher.addImageCache(getSupportFragmentManager(), new ImageCacheParams(this, CACHE_DIR_THUMBNAIL));
		
		mMovieListAdapter = new MovieListAdapter();
		
		mLayoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		mLoadingProgress = (LinearLayout) mLayoutInflater.inflate(R.layout.loading_progress_small, null);
    	
		mMovieListView = (ListView) findViewById(R.id.list);
		mMovieListView.setDividerHeight(0);
		mMovieListView.addHeaderView(mLoadingProgress);
		mMovieListView.setAdapter(mMovieListAdapter);
		mMovieListView.setOnItemClickListener(this);
		mMovieListView.setOnScrollListener(this);
		
		registerForContextMenu(mMovieListView);
		
		mResultPage = 1;
		mAmmWebService = AmmWebService.getInstance(this);
		
		Hashtable<String, String> params = new Hashtable<String, String>();
		params.put("page", Integer.toString(mResultPage));
		
		mAmmWebService.getMovies(params, new BasicAsyncCallback() {

			public void onComplete(final WebserviceObject[] result, final Object state) {
				
				Movie[] movies = (Movie[]) result;

				if ((movies != null)) {
					
					mPageCount = mAmmWebService.getResultPageCount();
					
					runOnUiThread(new Runnable() {public void run() { mMovieListView.removeHeaderView(mLoadingProgress); }});
															
					for (int i = 0; i < movies.length; i++) {
						
						final Movie movie = (Movie) (movies[i]);
						
						runOnUiThread(new Runnable() {public void run() { mMovieListAdapter.add(movie); }});
						
					}
				} 
			}

			public void onHttpClientException(final HttpClientException e, final Object state) {
				Log.w("AMM HttpClientException:", e.getMessage());
			}
			
			public void onIOException(final IOException e, final Object state) {
				Log.w("AMM IOException:", e.getMessage());
			}

			public void onWebServiceException(final WebServiceException e, final Object state) {
				Log.w("AMM WebServiceException:", e.getMessage());
				toastMessage(e.getMessage());
			}

		}, null);
	}
	
	@Override
    public void onResume() {
        super.onResume();
        mThumbnailImageFetcher.setExitTasksEarly(false);
        mMovieListAdapter.notifyDataSetChanged();
    }

    @Override
    public void onPause() {
        super.onPause();
        mThumbnailImageFetcher.setPauseWork(false);
        mThumbnailImageFetcher.setExitTasksEarly(true);
        mThumbnailImageFetcher.flushCache();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mThumbnailImageFetcher.closeCache();
    }
    
    @Override
	public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    	final Intent intent = new Intent(this, MovieDetailActivity.class);
		intent.putExtra(MovieDetailActivity.EXTRA_MOVIE_ID, (int) id);
        startActivity(intent);
	}
    
    @Override
	public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
		mLastItemVisible = (totalItemCount > 0) && (firstVisibleItem + visibleItemCount >= totalItemCount - 1);
	}

	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
		/**
		 * Check that the scrolling has stopped, and that the last item is
		 * visible.
		 */
		if ((scrollState == OnScrollListener.SCROLL_STATE_IDLE) && mLastItemVisible) {

			//check if we still have more page left and we aren't loading any data
			if ((mResultPage < mPageCount) && (!mLoadingInProgress)) {
				mMovieListView.addFooterView(mLoadingProgress);
				mResultPage++;
				loadMoreMovie();
				mLastItemVisible = false;
				mLoadingInProgress = true;
			}
			
		}
		
		// Pause fetcher to ensure smoother scrolling when flinging
        if (scrollState == OnScrollListener.SCROLL_STATE_FLING) {
            mThumbnailImageFetcher.setPauseWork(true);
        } else {
            mThumbnailImageFetcher.setPauseWork(false);
        }
	}

	 @Override
     public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
         super.onCreateContextMenu(menu, v, menuInfo);
         menu.add(Menu.NONE, R.id.context_menu_preview, Menu.NONE, R.string.preview);
         menu.add(Menu.NONE, R.id.context_menu_play, Menu.NONE, R.string.play);
         menu.add(Menu.NONE, R.id.context_menu_wishlist, Menu.NONE, R.string.add_to_wishlist);
         menu.add(Menu.NONE, R.id.context_menu_playlist, Menu.NONE, R.string.add_to_playlist);
     }
	 
	 @Override
     public boolean onContextItemSelected(MenuItem item) {
		 AdapterContextMenuInfo contextMenuInfo = (AdapterContextMenuInfo) item.getMenuInfo();
         switch (item.getItemId()) {
             case R.id.context_menu_preview:
                 playMovie((int) contextMenuInfo.id, R.string.preview);
                 return true;
             case R.id.context_menu_play:
                 playMovie((int) contextMenuInfo.id, R.string.play);
                 return true;
             case R.id.context_menu_wishlist:
                 addWishlist((int) contextMenuInfo.id, null);
                 return true;
             case R.id.context_menu_playlist:
            	 addPlaylist((int) contextMenuInfo.id, null);
                 return true;    
         }
         return super.onContextItemSelected(item);
     }
	 
	public void loadMoreMovie() {

	 	Hashtable<String, String> params = new Hashtable<String, String>();
		params.put("page", Integer.toString(mResultPage));

		mAmmWebService.getMovies(params, new BasicAsyncCallback() {

		public void onComplete(final WebserviceObject[] result, final Object state) {

			runOnUiThread(new Runnable() {public void run() { mMovieListView.removeFooterView(mLoadingProgress); }});
			
			mLoadingInProgress = false;
			
			Movie[] movies = (Movie[]) result;

			if ((movies != null)) {
																	
				for (int i = 0; i < movies.length; i++) {
					
					final Movie movie = (Movie) (movies[i]);
					
					runOnUiThread(new Runnable() {public void run() { mMovieListAdapter.add(movie); }});
					
				}
			} 
		}

		public void onHttpClientException(final HttpClientException e, final Object state) {
			mLoadingInProgress = false;
			runOnUiThread(new Runnable() {public void run() { mMovieListView.removeFooterView(mLoadingProgress); }});
			Log.w("AMM WebServiceException:", e.getMessage());
		}
		
		public void onIOException(final IOException e, final Object state) {
			mLoadingInProgress = false;
			runOnUiThread(new Runnable() {public void run() { mMovieListView.removeFooterView(mLoadingProgress); }});
			Log.w("AMM WebServiceException:", e.getMessage());
		}

		public void onWebServiceException(final WebServiceException e, final Object state) {
			mLoadingInProgress = false;
			runOnUiThread(new Runnable() {public void run() { mMovieListView.removeFooterView(mLoadingProgress); }});
			Log.w("AMM WebServiceException:", e.getMessage());
			toastMessage(e.getMessage());
		}

	}, null);

}
	
    public class MovieListAdapter extends BaseAdapter {

		private Vector<Movie> mListElements = new Vector<Movie>();
		
		private class ViewHolder {
			public TextView mMovieTitle;
			public TextView mMovieCast;
    	    public ImageView mMovieCover;
    	    public ImageView mMovieRating;
    	}
		
        public MovieListAdapter() {
        }

        public int getCount() {
        	if (mListElements.isEmpty()) {
    			return 0;
    		} else {
    			return mListElements.size();
    		}
        }

        public Object getItem(int position) {
        	Movie movie = (Movie) mListElements.elementAt(position);
        	return movie;
        }

        public long getItemId(int position) {
        	Movie movie = (Movie) mListElements.elementAt(position);
    		return movie.getId();
        }

        public View getView(int position, View convertView, ViewGroup parent) {

        	Movie movie = (Movie) mListElements.elementAt(position);

        	ViewHolder holder;
        	
        	View movieRow = convertView;
        	
        	if(movieRow == null){
            	movieRow = mLayoutInflater.inflate(R.layout.movie_listview_row, parent, false);
            	
            	holder  = new ViewHolder();
        		holder.mMovieTitle = (TextView) movieRow.findViewById(R.id.movie_title);
        		holder.mMovieCast = (TextView) movieRow.findViewById(R.id.movie_cast);
        		holder.mMovieRating = (ImageView) movieRow.findViewById(R.id.movie_rating);
        		holder.mMovieCover = (ImageView) movieRow.findViewById(R.id.movie_cover);
        		
        		movieRow.setTag(holder);
        	}else{
        		holder = (ViewHolder) movieRow.getTag();
        	}
        	
        	holder.mMovieTitle.setText(movie.getTitle());
        	holder.mMovieCast.setText(movie.getShortCast());
        	holder.mMovieRating.setImageResource(mRatingsStarDarkArray[movie.getRatings()]);
        	mThumbnailImageFetcher.loadImage(movie.getCover(), holder.mMovieCover);
  
        	return movieRow;
        }
        
        public void add(Movie data) {
        	mListElements.addElement(data);
            notifyDataSetChanged();
        }

    }

}
